﻿using FileImportSystem2.Db.Entities;
using FileImportSystem2.Services;
using SQLite;
using SQLitePCL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace FileImportSystem2.Forms
{
    public partial class MainForm : Form
    {
        // 记录选择的文件列表
        private List<string> _selectedFiles = null!;
        private bool isHaveMissing = true;
        string dtStr = string.Empty;

        // 记录导入时间，计算耗时
        private DateTime dt;
        #region 初始化窗体
        public MainForm()
        {
            InitializeComponent();
            // 新增下面2行代码，在主窗体显示版本号
            var file = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
            this.Text = this.Text + " - " + file.FileVersion;
            // 设置窗体边框为固定对话框样式，禁止拖拽缩放
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            // 禁用最大化按钮
            this.MaximizeBox = false;



            // 修正：将 Resource1.xhs_icon (byte[]) 转换为 Icon
            using (var ms = new MemoryStream(Resource1.xhs_icon))
            {
                this.Icon = new Icon(ms);
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            updateCmbMonth();
            LogMessage("系统已启动，准备就绪。");
        }

        private void updateCmbMonth()
        {
            string _dbFd = AppConfig.dbMonFd;
            Directory.CreateDirectory(_dbFd);

            string[] files = Directory.GetFiles(_dbFd, "*.db");

            cmbMonth.Items.Clear();
            // 初始化月份下拉框,使用已有的月份文件
            foreach (var file in files)
            {

                string fileName = Path.GetFileNameWithoutExtension(file);
                cmbMonth.Items.Add(fileName);
            }
            // 默认选择当前月份
            if (cmbMonth.Items.Count > 0)
            {
                cmbMonth.SelectedIndex = cmbMonth.Items.Count - 1;
            }
            else
            {
                LogMessage("未找到任何月份数据库文件，请先导入数据。");
                btnExportData.Enabled = false;
                btnExportMissingInfo.Enabled = false;
            }
        }
        #endregion

        #region 日志记录
        private void LogMessage(string message)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke(new Action<string>(LogMessage), message);
            }
            else
            {
                string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}\n";
                txtLog.AppendText(logEntry);
                txtLog.ScrollToCaret();

                // 同时写入本地日志文件
                try
                {
                    string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
                    if (!Directory.Exists(logDirectory))
                    {
                        Directory.CreateDirectory(logDirectory);
                    }

                    string logFileName = $"{DateTime.Now:yyyyMMdd}.log";
                    string logFilePath = Path.Combine(logDirectory, logFileName);

                    using (StreamWriter writer = new StreamWriter(logFilePath, append: true))
                    {
                        writer.WriteLine(logEntry.TrimEnd('\n'));
                    }
                }
                catch (Exception ex)
                {
                    // 如果写入日志文件失败，记录在界面上但不抛出异常
                    string errorEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 写入日志文件失败: {ex.Message}\n";
                    txtLog.AppendText(errorEntry);
                    txtLog.ScrollToCaret();
                }
            }
        }
        #endregion

        #region 导入数据库后台任务处理
        private void backgroundWorker1_DoWorkAsync(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            int totalFiles = _selectedFiles.Count;
            int successCount = 0;
            int failCount = 0;

            int totalImported = 0;
            int runType = 1;

            switch (runType)
            {
                case 1:
                    for (int i = 0; i < _selectedFiles.Count; i++)
                    {
                        string file = _selectedFiles[i];
                        LogMessage($"开始处理文件[{i + 1}/{totalFiles}]: {file}");
                        // 模拟处理文件的耗时操作
                        var importer = new Services.FileImporterService(file);
                        (bool res, string mark, int ImpNum) = importer.Import();

                        if (res)
                        {
                            successCount++;
                            LogMessage($"文件处理成功[{i + 1}/{totalFiles}]: 记录数: {ImpNum}");
                            totalImported += ImpNum;
                        }
                        else
                        {
                            failCount++;
                            LogMessage($"文件处理失败[{i + 1}/{totalFiles}]: {mark}");
                        }
                        // 更新进度
                        int progressPercentage = (int)(((i + 1) / (float)_selectedFiles.Count) * 100);
                        backgroundWorker1.ReportProgress(progressPercentage);
                    }

                    e.Result = new
                    {
                        Success = failCount == 0,
                        Message = $"统计结果: (耗时 {(DateTime.Now - dt).ToString()}),成功 {successCount} 个，失败 {failCount} 个，总计导入 {totalImported} 条记录"
                    };
                    break;
                case 2:
                    Dictionary<string, Services.FileImporterService> dicDB = new Dictionary<string, Services.FileImporterService>();
                    // 使用线程安全的集合来收集每个任务的结果
                    System.Collections.Concurrent.ConcurrentBag<(bool res, string mark, int ImpNum)> resultsBag = new System.Collections.Concurrent.ConcurrentBag<(bool res, string mark, int ImpNum)>();
                    int processedCount = 0; // 已处理文件计数，用于进度报告
                    object lockObj = new object(); // 用于锁定计数操作

                    try
                    {
                        // 创建并行选项并设置最大并发数为 3
                        ParallelOptions options = new ParallelOptions
                        {
                            MaxDegreeOfParallelism = 5
                        };
                        // 使用 Parallel.ForEach 并行处理文件，但阻塞等待所有任务完成
                        Parallel.ForEach(_selectedFiles, options, (file) =>
                        {

                            LogMessage($"开始处理文件: {file}");

                            (string dateFull, string dateMonth) = FileNameServer.getDateFromFilePath(file);
                            Services.FileImporterService? importer;

                            // 注意：字典操作需要线程安全，这里使用锁来确保正确性
                            lock (dicDB)
                            {
                                if (!dicDB.TryGetValue(dateMonth, out importer))
                                {
                                    importer = new Services.FileImporterService(file);
                                    dicDB.Add(dateMonth, importer);
                                }
                            }

                            // 同步调用导入方法，并获取结果
                            var result = importer.Import(file); // 注意：这里应调用同步的 Import 方法
                            resultsBag.Add(result);


                            // 更新进度（需要线程安全操作）
                            int currentCount;
                            lock (lockObj)
                            {
                                processedCount++;
                                currentCount = processedCount;
                            }

                            if (!result.res)
                            {
                                // 如果 LogMessage 要更新UI，可能需要使用 Control.Invoke
                                LogMessage($"导入失败[{processedCount}/{totalFiles}]: {result.mark}:{file}");
                            }
                            else
                            {
                                LogMessage($"导入成功[{processedCount}/{totalFiles}]:处理数量: {result.ImpNum};路径：{file}");
                            }

                            // 报告进度（BackgroundWorker 能安全处理跨线程的进度报告）
                            int progressPercentage = (int)((currentCount / (float)_selectedFiles.Count) * 100);
                            backgroundWorker1.ReportProgress(progressPercentage, result); // 可传递结果用于实时显示
                        });

                        // 所有并行任务完成后，统计最终结果
                        successCount = resultsBag.Count(r => r.res);
                        failCount = resultsBag.Count(r => !r.res);
                        totalImported = resultsBag.Sum(r => r.ImpNum);

                        e.Result = new
                        {
                            Success = failCount == 0,
                            Message = $"统计结果: (耗时 {(DateTime.Now - dt).ToString()}),成功 {successCount} 个，失败 {failCount} 个，总计导入 {totalImported} 条记录"
                        };

                    }
                    catch (Exception ex)
                    {
                        LogMessage($"任务执行过程中发生异常: {ex.Message}");
                    }
                    break;

                default:
                    LogMessage("未知的处理类型，操作中止。");
                    e.Result = new
                    {
                        Success = false,
                        Message = "未知的处理类型，操作中止。"
                    };
                    return;
            }


        }

        private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            toolStripStatusLabel1.Text = $"处理中... {e.ProgressPercentage}%";
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            try
            {
                btnImportFiles.Enabled = true;
                btnExportData.Enabled = true;
                btnExportMissingInfo.Enabled = true;
                toolStripStatusLabel1.Text = "准备就绪 - 数据处理程序";

                if (e.Result != null)
                {
                    dynamic result = e.Result;
                    LogMessage(result.Message.ToString());

                    if ((bool)result.Success)
                    {
                        MessageBox.Show(result.Message.ToString(), "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                    {
                        MessageBox.Show(result.Message.ToString(), "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                // 重新加载月份列表
                updateCmbMonth();
            }
            catch (Exception ex)
            {
                LogMessage($"操作完成处理时出错：{ex.Message}");
            }
        }

        #endregion
        private void btnImportFiles_Click(object sender, EventArgs e)
        {
            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Multiselect = true;
                openFileDialog.Filter = "Excel文件 (*.xlsx;*.xls)|*.xlsx;*.xls|所有文件 (*.*)|*.*";
                openFileDialog.Title = "选择要导入的文件";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    // 选择了文件，开始处理
                    _selectedFiles = openFileDialog.FileNames.ToList();

                    // 导入新的数据，需要核对缺失信息
                    isHaveMissing = true;

                    if (!backgroundWorker1.IsBusy)
                    {
                        dt = DateTime.Now;
                        LogMessage($"开始导入{_selectedFiles.Count}个文件...");
                        btnImportFiles.Enabled = false;
                        btnExportData.Enabled = false;
                        btnExportMissingInfo.Enabled = false;
                        backgroundWorker1.RunWorkerAsync();

                    }
                }
            }
        }

        private async void btnExportMissingInfo_Click(object sender, EventArgs e)
        {
            btnExportMissingInfo.Enabled = false; // 防止重复点击
            string updateMon = cmbMonth.Text;
            bool isMatchInit = chbisMatchInit.Checked;
            dtStr = DateTime.Now.ToString("yyyyMMdd_HHmmss");

            await funExpMissInfo(updateMon, isMatchInit);

            btnExportMissingInfo.Enabled = true;
        }

        private async void btnExportData_Click(object sender, EventArgs e)
        {
            // 导出月份
            string updateMon = cmbMonth.Text;
            // 是否匹配初始数据
            bool isMatchInit = chbisMatchInit.Checked;
            dtStr = DateTime.Now.ToString("yyyyMMdd_HHmmss");

            btnExportData.Enabled = false;
            if (isHaveMissing)
            {
                LogMessage("核对数据缺失情况");
                await funExpMissInfo(updateMon, isMatchInit);
            }
            await funExpDt(updateMon);
            btnExportData.Enabled = true;
        }


        private async Task funExpMissInfo(string updateMon, bool isMatchInit)
        {
            isHaveMissing = true;
            try
            {
                var progress = new Progress<string>(message =>
                {
                    // 这个回调会在UI线程上自动执行
                    LogMessage(message);
                });

                // 匹配数据库
                dbMatchServer _dbs = new(updateMon, progress);
                if (_dbs._isInit)
                {
                    await Task.Run(() => _dbs.dbMatch(2, isMatchInit));
                    _dbs.Dispose();// 释放资源
                    LogMessage("数据库匹配操作已完成。");
                }
                else
                {
                    LogMessage($"数据库匹配操作异常:{_dbs._initError}");
                }


                // 导出缺失信息
                dbExportServer _dbExport = new(updateMon, progress, dtStr: dtStr);
                if (_dbExport._isInit)
                {
                    bool isMissing = false;
                    string expDictory = string.Empty;
                    await Task.Run(() => isMissing = _dbExport.TryExportUnMatchedData(out expDictory));
                    _dbExport.Dispose();//释放资源
                    if (isMissing)
                    {
                        LogMessage($"已输出缺失信息,目录：{expDictory}");
                    }
                    else
                    {
                        LogMessage($"没有缺失信息,可直接导出结果！");
                        isHaveMissing = false;
                    }
                }
                else
                {
                    LogMessage($"数据库导出操作异常:{_dbExport._initError}");
                }


            }
            catch (Exception ex)
            {
                LogMessage($"操作发生错误: {ex.Message}");
            }

        }

        private async Task funExpDt(string updateMon)
        {
            try
            {
                var progress = new Progress<string>(message =>
                {
                    // 这个回调会在UI线程上自动执行
                    LogMessage(message);
                });

                LogMessage($"开始导出{updateMon}统计数据");
                dbExportServer _dbExport = new(updateMon, progress, dtStr: dtStr);
                if (_dbExport._isInit)
                {
                    bool isExp = false;
                    string expDictory = string.Empty;
                    await Task.Run(() => isExp = _dbExport.TryExportResultData(out expDictory));
                    _dbExport.Dispose();//释放资源
                    if (isExp)
                    {
                        LogMessage($"已输出汇总信息,目录：{expDictory}");
                    }
                    else
                    {
                        LogMessage($"没有数据可输出");
                    }
                }
                else
                {
                    LogMessage($"数据库导出操作异常:{_dbExport._initError}");
                }
            }
            catch (Exception ex)
            {
                LogMessage($"操作发生错误: {ex.Message}");
            }
        }

        private void lblMonth_DoubleClick(object sender, EventArgs e)
        {
            string dbFd = AppConfig.dbMonFd;
            string dbMonth = cmbMonth.Text;
            string dbPath = Path.Combine(dbFd, dbMonth + ".db");
            if (File.Exists(dbPath))
            {
                Process.Start("explorer.exe", $"/select,\"{dbPath}\"");
            }
        }

        private void lblMonth_Click(object sender, EventArgs e)
        {
            updateCmbMonth();
        }

        private void btnExpBySql_Click(object sender, EventArgs e)
        {
            dtStr = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            string dbMonth = cmbMonth.Text;
           string outputDir =  Path.Combine(AppConfig.GetSafeAppDataPath(), "exp", dtStr);
            var progress = new Progress<string>(message =>
            {
                // 这个回调会在UI线程上自动执行
                LogMessage(message);
            });

            dbExportServer _dbExport = new(dbMonth, progress, dtStr: dtStr);

           string sql =  SimpleInputBox ("自定义SQL导出", "请输入SQL语句：");

            _dbExport.TryExportData(sql, out string filePath, outputDir: outputDir, fileName: $"自定义SQL导出_{dtStr}.xlsx", rowCount: -1);
            LogMessage($"已输出自定义SQL导出,目录：{filePath}");   
        }

        public static string SimpleInputBox(string caption, string prompt)
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button okButton = new Button();

            form.Text = caption;
            label.Text = prompt;
            okButton.Text = "OK";
            okButton.DialogResult = DialogResult.OK;

            label.SetBounds(10, 20, 260, 13);
            textBox.SetBounds(10, 40, 980, 20);
            okButton.SetBounds(100, 70, 75, 23);

            form.ClientSize = new Size(1000, 110);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.Controls.AddRange(new Control[] { label, textBox, okButton });
            form.AcceptButton = okButton;

            string result = "";
            okButton.Click += (sender, e) => { result = textBox.Text; form.Close(); };

            form.ShowDialog(); // 使用ShowDialog()使其成为模态对话框
            return result;
        }
    }
}
